package com.ssy.lingxi.marketing.serviceimpl;

import com.ssy.lingxi.common.constant.marketing.BelongTypeEnum;
import com.ssy.lingxi.common.constant.marketing.MerchantCouponTypeEnum;
import com.ssy.lingxi.common.constant.member.AbilitySuitableMemberEnum;
import com.ssy.lingxi.common.exception.BusinessException;
import com.ssy.lingxi.common.model.dto.UserLoginCacheDTO;
import com.ssy.lingxi.common.model.vo.MemberAndRoleIdVO;
import com.ssy.lingxi.common.model.vo.SelectItemVO;
import com.ssy.lingxi.common.response.PageData;
import com.ssy.lingxi.common.response.ResponseCode;
import com.ssy.lingxi.common.response.Wrapper;
import com.ssy.lingxi.marketing.entity.coupon.CouponGoodsDO;
import com.ssy.lingxi.marketing.entity.coupon.MerchantCouponDO;
import com.ssy.lingxi.marketing.entity.coupon.MerchantCouponDetailDO;
import com.ssy.lingxi.marketing.model.constant.*;
import com.ssy.lingxi.marketing.model.dto.CountCouponDetailDTO;
import com.ssy.lingxi.marketing.model.vo.common.request.CommonAgreeRequest;
import com.ssy.lingxi.marketing.model.vo.common.request.CommonIdReq;
import com.ssy.lingxi.marketing.model.vo.common.request.CommonIdsRequest;
import com.ssy.lingxi.marketing.model.vo.common.response.TaskStepVO;
import com.ssy.lingxi.marketing.model.vo.coupon.request.*;
import com.ssy.lingxi.marketing.model.vo.coupon.response.*;
import com.ssy.lingxi.marketing.repository.*;
import com.ssy.lingxi.marketing.service.IMerchantCouponService;
import com.ssy.lingxi.marketing.service.IProcessFeignService;
import com.ssy.lingxi.marketing.service.IScheduleFeignService;
import com.ssy.lingxi.marketing.service.feign.IMemberFeignService;
import com.ssy.lingxi.marketing.service.feign.IOrderFeignService;
import com.ssy.lingxi.marketing.service.feign.IPlatformManageFeignService;
import com.ssy.lingxi.marketing.serviceimpl.base.coupon.BaseCouponGoodsService;
import com.ssy.lingxi.marketing.serviceimpl.base.coupon.BaseCouponRecordService;
import com.ssy.lingxi.marketing.serviceimpl.base.coupon.BaseCouponRuleService;
import com.ssy.lingxi.marketing.serviceimpl.base.coupon.BaseMerchantCouponService;
import com.ssy.lingxi.marketing.serviceimpl.component.SuitableFieldComponent;
import com.ssy.lingxi.marketing.serviceimpl.component.coupon.CouponQueryComponent;
import com.ssy.lingxi.marketing.serviceimpl.component.coupon.CouponReceiveComponent;
import com.ssy.lingxi.marketing.utils.NumberUtil;
import com.ssy.lingxi.member.merchant.api.model.vo.inner.response.MemberFeignLevelConfigVO;
import com.ssy.lingxi.order.api.model.vo.response.OrderAfterSaleStatusVO;
import com.ssy.lingxi.platform.manage.api.model.vo.shop.ShopVO;
import com.ssy.lingxi.product.api.model.response.BrandResponse;
import com.ssy.lingxi.product.api.model.response.commodity.CustomerCategoryResponse;
import com.ssy.lingxi.workflow.api.model.contant.ProcessTaskStatusEnum;
import com.ssy.lingxi.workflow.api.model.vo.request.InternalProcessQueryVO;
import com.ssy.lingxi.workflow.api.model.vo.request.TaskExecuteVO;
import com.ssy.lingxi.workflow.api.model.vo.request.TaskStartVO;
import com.ssy.lingxi.workflow.api.model.vo.response.SimpleProcessDefVO;
import com.ssy.lingxi.workflow.api.model.vo.response.SimpleTaskCompleteVO;
import com.ssy.lingxi.workflow.api.model.vo.response.SimpleTaskVO;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.StringUtils;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

import javax.annotation.Resource;
import javax.persistence.criteria.Predicate;
import java.util.*;
import java.util.stream.Collectors;
import java.util.stream.Stream;

/**
 * 商家优惠券服务实现类
 * @author yzc
 * @version 2.0.0
 * @date 2021/6/25
 */
@Slf4j
@Service
public class MerchantCouponServiceImpl extends BaseMerchantCouponService implements IMerchantCouponService {

    @Resource
    private MerchantCouponRepository merchantCouponRepository;
    @Resource
    private MerchantCouponDetailRepository merchantCouponDetailRepository;
    @Resource
    private BaseCouponRecordService baseCouponRecordService;
    @Resource
    private IProcessFeignService processFeignService;
    @Resource
    private IPlatformManageFeignService platformManageService;
    @Resource
    private IMemberFeignService memberFeignService;
    @Resource
    private CouponGoodsRepository goodsRepository;
    @Resource
    private CouponCategoryRepository categoryRepository;
    @Resource
    private CouponBrandRepository brandRepository;
    @Resource
    private CouponMemberLevelRepository memberLevelRepository;
    @Resource
    private CouponShopRepository shopRepository;
    @Resource
    private IScheduleFeignService scheduleFeignService;
    @Resource
    private BaseCouponRuleService baseCouponRuleService;
    @Resource
    private BaseCouponGoodsService baseCouponGoodsService;
    @Resource
    private CouponReceiveComponent couponReceiveComponent;
    @Resource
    private CouponQueryComponent couponQueryComponent;
    @Resource
    private IOrderFeignService orderFeignService;

    @Override
    public Wrapper<PageData<MerchantCouponSummaryPageResponse>> pageSummaryMerchantCoupon(MerchantCouponPageRequest request, UserLoginCacheDTO loginUser) {
        List<Integer> statusList = NumberUtil.notNullOrZero(request.getStatus()) ? Collections.singletonList(request.getStatus()) : Collections.emptyList();
        request.setSortName("releaseTimeStart");
        Page<MerchantCouponDO> pageList = basePageMerchantCoupon(request, statusList, loginUser);
        List<MerchantCouponSummaryPageResponse> resultList = pageList.stream().map(coupon -> {
            MerchantCouponSummaryPageResponse response = new MerchantCouponSummaryPageResponse();
            response.setId(coupon.getId());
            response.setName(coupon.getName());
            response.setType(coupon.getType());
            response.setTypeName(MerchantCouponTypeEnum.getCodeMessage(coupon.getType()));
            response.setReleaseTimeStart(coupon.getReleaseTimeStart());
            response.setReleaseTimeEnd(coupon.getReleaseTimeEnd());
            response.setDenomination(coupon.getDenomination());
            response.setQuantity(coupon.getQuantity());
            response.setGetWay(coupon.getGetWay());
            response.setGetWayName(MerchantCouponGetWayEnum.getCodeMessage(coupon.getGetWay()));
            response.setEffectiveType(coupon.getEffectiveType());
            response.setEffectiveTimeStart(coupon.getEffectiveTimeStart());
            response.setEffectiveTimeEnd(coupon.getEffectiveTimeEnd());
            response.setInvalidDay(coupon.getInvalidDay());
            response.setStatus(coupon.getStatus());
            response.setStatusName(MerchantCouponStatusEnum.getCodeMessage(coupon.getStatus()));
            response.setCreateTime(coupon.getCreateTime());
            response.setUpdate(Arrays.asList(MerchantCouponStatusEnum.WAIT_EXECUTE.getCode(),
                    MerchantCouponStatusEnum.EXECUTING.getCode(),
                    MerchantCouponStatusEnum.STOP.getCode()).contains(coupon.getStatus())
            );
            response.setCancel(MerchantCouponStatusEnum.WAIT_EXECUTE.getCode().equals(coupon.getStatus()));
            response.setStop(MerchantCouponStatusEnum.EXECUTING.getCode().equals(coupon.getStatus()));
            response.setRestart(MerchantCouponStatusEnum.STOP.getCode().equals(coupon.getStatus()));
            return response;
        }).collect(Collectors.toList());

        return Wrapper.success(new PageData<>(pageList.getTotalElements(), resultList));
    }

    @Override
    public Wrapper<PageData<MerchantCouponSubmitAuditPageResponse>> pageSubmitAuditMerchantCoupon(MerchantCouponPageRequest request, UserLoginCacheDTO loginUser) {
        List<Integer> statusList = Arrays.asList(
                MerchantCouponStatusEnum.WAIT_SUBMIT_AUDIT.getCode(),
                MerchantCouponStatusEnum.WAIT_AUDIT_1_REJECT.getCode(),
                MerchantCouponStatusEnum.WAIT_AUDIT_2_REJECT.getCode()
        );
        Page<MerchantCouponDO> pageList = basePageMerchantCoupon(request, statusList, loginUser);
        List<MerchantCouponSubmitAuditPageResponse> resultList = pageList.stream().map(coupon -> {
            MerchantCouponSubmitAuditPageResponse response = new MerchantCouponSubmitAuditPageResponse();
            response.setId(coupon.getId());
            response.setName(coupon.getName());
            response.setType(coupon.getType());
            response.setTypeName(MerchantCouponTypeEnum.getCodeMessage(coupon.getType()));
            response.setReleaseTimeStart(coupon.getReleaseTimeStart());
            response.setReleaseTimeEnd(coupon.getReleaseTimeEnd());
            response.setDenomination(coupon.getDenomination());
            response.setQuantity(coupon.getQuantity());
            response.setGetWay(coupon.getGetWay());
            response.setGetWayName(MerchantCouponGetWayEnum.getCodeMessage(coupon.getGetWay()));
            response.setEffectiveType(coupon.getEffectiveType());
            response.setEffectiveTimeStart(coupon.getEffectiveTimeStart());
            response.setEffectiveTimeEnd(coupon.getEffectiveTimeEnd());
            response.setInvalidDay(coupon.getInvalidDay());
            response.setStatus(coupon.getStatus());
            response.setStatusName(MerchantCouponStatusEnum.getCodeMessage(coupon.getStatus()));
            response.setCreateTime(coupon.getCreateTime());
            response.setSubmit(MerchantCouponStatusEnum.WAIT_SUBMIT_AUDIT.getCode().equals(coupon.getStatus()));
            response.setDelete(MerchantCouponStatusEnum.WAIT_SUBMIT_AUDIT.getCode().equals(coupon.getStatus()));
            response.setUpdate(Arrays.asList(MerchantCouponStatusEnum.WAIT_SUBMIT_AUDIT.getCode(), MerchantCouponStatusEnum.WAIT_AUDIT_1_REJECT.getCode(), MerchantCouponStatusEnum.WAIT_AUDIT_2_REJECT.getCode()).contains(coupon.getStatus()));
            return response;
        }).collect(Collectors.toList());

        return Wrapper.success(new PageData<>(pageList.getTotalElements(), resultList));
    }

    @Override
    public Wrapper<PageData<MerchantCouponAuditPageResponse>> pageAuditOneMerchantCoupon(MerchantCouponPageRequest request, UserLoginCacheDTO loginUser) {
        List<Integer> statusList = Collections.singletonList(MerchantCouponStatusEnum.WAIT_AUDIT_1.getCode());
        Page<MerchantCouponDO> pageList = basePageMerchantCoupon(request, statusList, loginUser);
        List<MerchantCouponAuditPageResponse> resultList = pageList.stream().map(coupon -> {
            MerchantCouponAuditPageResponse response = new MerchantCouponAuditPageResponse();
            response.setId(coupon.getId());
            response.setName(coupon.getName());
            response.setType(coupon.getType());
            response.setTypeName(MerchantCouponTypeEnum.getCodeMessage(coupon.getType()));
            response.setReleaseTimeStart(coupon.getReleaseTimeStart());
            response.setReleaseTimeEnd(coupon.getReleaseTimeEnd());
            response.setDenomination(coupon.getDenomination());
            response.setQuantity(coupon.getQuantity());
            response.setGetWay(coupon.getGetWay());
            response.setGetWayName(MerchantCouponGetWayEnum.getCodeMessage(coupon.getGetWay()));
            response.setEffectiveType(coupon.getEffectiveType());
            response.setEffectiveTimeStart(coupon.getEffectiveTimeStart());
            response.setEffectiveTimeEnd(coupon.getEffectiveTimeEnd());
            response.setInvalidDay(coupon.getInvalidDay());
            response.setStatus(coupon.getStatus());
            response.setStatusName(MerchantCouponStatusEnum.getCodeMessage(coupon.getStatus()));
            response.setCreateTime(coupon.getCreateTime());
            response.setAudit(MerchantCouponStatusEnum.WAIT_AUDIT_1.getCode().equals(coupon.getStatus()));
            return response;
        }).collect(Collectors.toList());

        return Wrapper.success(new PageData<>(pageList.getTotalElements(), resultList));
    }

    @Override
    public Wrapper<PageData<MerchantCouponAuditPageResponse>> pageAuditTwoMerchantCoupon(MerchantCouponPageRequest request, UserLoginCacheDTO loginUser) {
        List<Integer> statusList = Collections.singletonList(MerchantCouponStatusEnum.WAIT_AUDIT_2.getCode());
        Page<MerchantCouponDO> pageList = basePageMerchantCoupon(request, statusList, loginUser);
        List<MerchantCouponAuditPageResponse> resultList = pageList.stream().map(coupon -> {
            MerchantCouponAuditPageResponse response = new MerchantCouponAuditPageResponse();
            response.setId(coupon.getId());
            response.setName(coupon.getName());
            response.setType(coupon.getType());
            response.setTypeName(MerchantCouponTypeEnum.getCodeMessage(coupon.getType()));
            response.setReleaseTimeStart(coupon.getReleaseTimeStart());
            response.setReleaseTimeEnd(coupon.getReleaseTimeEnd());
            response.setDenomination(coupon.getDenomination());
            response.setQuantity(coupon.getQuantity());
            response.setGetWay(coupon.getGetWay());
            response.setGetWayName(MerchantCouponGetWayEnum.getCodeMessage(coupon.getGetWay()));
            response.setEffectiveType(coupon.getEffectiveType());
            response.setEffectiveTimeStart(coupon.getEffectiveTimeStart());
            response.setEffectiveTimeEnd(coupon.getEffectiveTimeEnd());
            response.setInvalidDay(coupon.getInvalidDay());
            response.setStatus(coupon.getStatus());
            response.setStatusName(MerchantCouponStatusEnum.getCodeMessage(coupon.getStatus()));
            response.setCreateTime(coupon.getCreateTime());
            response.setAudit(MerchantCouponStatusEnum.WAIT_AUDIT_2.getCode().equals(coupon.getStatus()));
            return response;
        }).collect(Collectors.toList());

        return Wrapper.success(new PageData<>(pageList.getTotalElements(), resultList));
    }

    @Override
    public Wrapper<PageData<MerchantCouponSubmitPageResponse>> pageSubmitMerchantCoupon(MerchantCouponPageRequest request, UserLoginCacheDTO loginUser) {
        List<Integer> statusList = Collections.singletonList(MerchantCouponStatusEnum.WAIT_SUBMIT.getCode());
        Page<MerchantCouponDO> pageList = basePageMerchantCoupon(request, statusList, loginUser);
        List<MerchantCouponSubmitPageResponse> resultList = pageList.stream().map(coupon -> {
            MerchantCouponSubmitPageResponse response = new MerchantCouponSubmitPageResponse();
            response.setId(coupon.getId());
            response.setName(coupon.getName());
            response.setType(coupon.getType());
            response.setTypeName(MerchantCouponTypeEnum.getCodeMessage(coupon.getType()));
            response.setReleaseTimeStart(coupon.getReleaseTimeStart());
            response.setReleaseTimeEnd(coupon.getReleaseTimeEnd());
            response.setDenomination(coupon.getDenomination());
            response.setQuantity(coupon.getQuantity());
            response.setGetWay(coupon.getGetWay());
            response.setGetWayName(MerchantCouponGetWayEnum.getCodeMessage(coupon.getGetWay()));
            response.setEffectiveType(coupon.getEffectiveType());
            response.setEffectiveTimeStart(coupon.getEffectiveTimeStart());
            response.setEffectiveTimeEnd(coupon.getEffectiveTimeEnd());
            response.setInvalidDay(coupon.getInvalidDay());
            response.setStatus(coupon.getStatus());
            response.setStatusName(MerchantCouponStatusEnum.getCodeMessage(coupon.getStatus()));
            response.setCreateTime(coupon.getCreateTime());
            response.setSubmit(MerchantCouponStatusEnum.WAIT_SUBMIT.getCode().equals(coupon.getStatus()));
            return response;
        }).collect(Collectors.toList());

        return Wrapper.success(new PageData<>(pageList.getTotalElements(), resultList));
    }

    @Override
    public Wrapper<PageData<MerchantCouponExecutePageResponse>> pageExecuteMerchantCoupon(MerchantCouponPageRequest request, UserLoginCacheDTO loginUser) {
        List<Integer> statusList = Arrays.asList(MerchantCouponStatusEnum.WAIT_EXECUTE.getCode(),
                MerchantCouponStatusEnum.EXECUTING.getCode(), MerchantCouponStatusEnum.STOP.getCode(),
                MerchantCouponStatusEnum.CANCEL.getCode(), MerchantCouponStatusEnum.FINISH.getCode());

        Page<MerchantCouponDO> pageList = basePageMerchantCoupon(request, statusList, loginUser);
        if (CollectionUtils.isEmpty(pageList.getContent())) {
            return Wrapper.success(new PageData<>(0L, Collections.emptyList()));
        }

        // 统计数量
        List<Long> couponIdList = pageList.stream().map(MerchantCouponDO::getId).collect(Collectors.toList());

        List<CountCouponDetailDTO> countCouponDetailDTOList = couponQueryComponent.countMerchantCouponDetail(couponIdList);
        Map<Long, CountCouponDetailDTO> couponMap = countCouponDetailDTOList.stream().collect(Collectors.toMap(e -> e.getCouponId(), e -> e, (e1, e2) -> e2));

        List<MerchantCouponExecutePageResponse> resultList = pageList.stream().map(coupon -> {
            MerchantCouponExecutePageResponse response = new MerchantCouponExecutePageResponse();
            response.setId(coupon.getId());
            response.setName(coupon.getName());
            response.setType(coupon.getType());
            response.setTypeName(MerchantCouponTypeEnum.getCodeMessage(coupon.getType()));
            response.setReleaseTimeStart(coupon.getReleaseTimeStart());
            response.setReleaseTimeEnd(coupon.getReleaseTimeEnd());
            response.setDenomination(coupon.getDenomination());
            response.setQuantity(coupon.getQuantity());
            response.setGetWay(coupon.getGetWay());
            response.setGetWayName(MerchantCouponGetWayEnum.getCodeMessage(coupon.getGetWay()));
            response.setEffectiveType(coupon.getEffectiveType());
            response.setEffectiveTimeStart(coupon.getEffectiveTimeStart());
            response.setEffectiveTimeEnd(coupon.getEffectiveTimeEnd());
            response.setInvalidDay(coupon.getInvalidDay());
            response.setStatus(coupon.getStatus());
            response.setStatusName(MerchantCouponStatusEnum.getCodeMessage(coupon.getStatus()));
            response.setCreateTime(coupon.getCreateTime());
            Integer obtainQuantityNum = Optional.ofNullable(couponMap.get(coupon.getId())).map(CountCouponDetailDTO::getObtainQuantity).orElse(0);
            Integer useQuantityNum = Optional.ofNullable(couponMap.get(coupon.getId())).map(CountCouponDetailDTO::getUseQuantity).orElse(0);
            Integer dueQuantityNum = Optional.ofNullable(couponMap.get(coupon.getId())).map(CountCouponDetailDTO::getDueQuantity).orElse(0);
            response.setObtainQuantity(obtainQuantityNum);
            response.setUseQuantity(useQuantityNum);
            response.setDueQuantity(dueQuantityNum);
            // 状态进行中, 且领取类型为指定会员, 且剩余领取数量大于0
            boolean releaseBtn = MerchantCouponStatusEnum.EXECUTING.getCode().equals(coupon.getStatus())
                    && MerchantCouponGetWayEnum.APPOINT.getCode().equals(coupon.getGetWay())
                    && (coupon.getQuantity() - obtainQuantityNum) > 0;
            response.setRelease(releaseBtn);
            return response;
        }).collect(Collectors.toList());

        return Wrapper.success(new PageData<>(pageList.getTotalElements(), resultList));
    }

    @Override
    public Wrapper<MerchantCouponResponse> getMerchantCoupon(CommonIdReq request, UserLoginCacheDTO loginUser) {
        MerchantCouponDO merchantCouponDO = merchantCouponRepository.findById(request.getId()).orElse(null);
        if (Objects.isNull(merchantCouponDO)) {
            return Wrapper.fail(ResponseCode.MARKETING_RECORDS_DONT_EXIST);
        }

        if (!isBelongCurrentMember(loginUser, merchantCouponDO.getMemberId(), merchantCouponDO.getRoleId())) {
            return Wrapper.fail(ResponseCode.MARKETING_RECORDS_DONT_EXIST);
        }

        MerchantCouponResponse response = new MerchantCouponResponse();
        response.setId(merchantCouponDO.getId());
        response.setName(merchantCouponDO.getName());
        response.setType(merchantCouponDO.getType());
        response.setTypeName(MerchantCouponTypeEnum.getCodeMessage(merchantCouponDO.getType()));
        response.setReleaseTimeStart(merchantCouponDO.getReleaseTimeStart());
        response.setReleaseTimeEnd(merchantCouponDO.getReleaseTimeEnd());
        response.setDenomination(merchantCouponDO.getDenomination());
        response.setQuantity(merchantCouponDO.getQuantity());
        response.setGetWay(merchantCouponDO.getGetWay());
        response.setGetWayName(MerchantCouponGetWayEnum.getCodeMessage(merchantCouponDO.getGetWay()));
        response.setConditionGetTotal(merchantCouponDO.getConditionGetTotal());
        response.setConditionGetDay(merchantCouponDO.getConditionGetDay());
        response.setEffectiveType(merchantCouponDO.getEffectiveType());
        response.setEffectiveTimeStart(merchantCouponDO.getEffectiveTimeStart());
        response.setEffectiveTimeEnd(merchantCouponDO.getEffectiveTimeEnd());
        response.setInvalidDay(merchantCouponDO.getInvalidDay());
        response.setUseConditionMoney(merchantCouponDO.getUseConditionMoney());
        response.setUseConditionDesc(merchantCouponDO.getUseConditionDesc());
        response.setStatus(merchantCouponDO.getStatus());
        response.setStatusName(MerchantCouponStatusEnum.getCodeMessage(merchantCouponDO.getStatus()));
        response.setCreateTime(merchantCouponDO.getCreateTime());

        response.setSuitableMemberTypes(SuitableFieldComponent.parseCouponSuitableUser(merchantCouponDO.getSuitableUser()).stream().map(e -> {
            AbilitySuitableMemberEnum abilitySuitableMemberEnum = AbilitySuitableMemberEnum.toEnum(e);
            return new SelectItemVO(abilitySuitableMemberEnum.getCode(), abilitySuitableMemberEnum.getMessage());
        }).collect(Collectors.toList()));

        // 当勾选了新会员或老会员才有适用等级
        List<SuitableMemberLevelVO> suitableMemberLevelVOList = Collections.emptyList();
        List<Integer> suitableUserList = SuitableFieldComponent.parseCouponSuitableUser(merchantCouponDO.getSuitableUser());
        if (suitableUserList.contains(AbilitySuitableMemberEnum.NEW_MEMBER.getCode())
                || suitableUserList.contains(AbilitySuitableMemberEnum.OLD_MEMBER.getCode())) {
            // 适用会员等级
            suitableMemberLevelVOList = baseCouponRuleService.listMemberLevel(BelongTypeEnum.MERCHANT, merchantCouponDO.getId());
        }
        response.setSuitableMemberLevelTypes(suitableMemberLevelVOList);

        // 适用商城
        response.setSuitableMallTypes(baseCouponRuleService.listShop(BelongTypeEnum.MERCHANT, merchantCouponDO.getId()));

        // 适用品类, 品牌, 商品
        if (MerchantCouponTypeEnum.CATEGORY.getCode().equals(merchantCouponDO.getType())) {
            // 品类
            response.setSuitableCategoryList(baseCouponGoodsService.listMerchantCouponCategory(merchantCouponDO.getId()));
        } else if (MerchantCouponTypeEnum.BRAND.getCode().equals(merchantCouponDO.getType())) {
            // 品牌
            response.setSuitableBrandList(baseCouponGoodsService.listMerchantCouponBrand(merchantCouponDO.getId()));
        } else if (MerchantCouponTypeEnum.COMMODITY.getCode().equals(merchantCouponDO.getType())) {
            // 商品
            response.setSuitableCommoditySkuList(baseCouponGoodsService.listMerchantCouponGoods(merchantCouponDO.getId()));
        } else if (MerchantCouponTypeEnum.ZERO_DISCOUNT.getCode().equals(merchantCouponDO.getType())) {
            // 0元抵扣
            response.setSuitableCommoditySkuList(baseCouponGoodsService.listMerchantCouponGoods(merchantCouponDO.getId()));
        }

        // 流转记录
        response.setHistory(baseCouponRecordService.listMerchantCouponRecord(merchantCouponDO));


        InternalProcessQueryVO internalProcessQueryVO = new InternalProcessQueryVO();
        internalProcessQueryVO.setProcessKey(MarketingConstants.merchant_coupon_key);
        internalProcessQueryVO.setTaskId(merchantCouponDO.getTaskId());
        internalProcessQueryVO.setMemberId(merchantCouponDO.getMemberId());

        Wrapper<SimpleProcessDefVO> result = processFeignService.findSimpleInternalTaskDefinitions(internalProcessQueryVO);
        if (result.getCode() == ResponseCode.SUCCESS.getCode()) {
            List<SimpleTaskVO> tasks = result.getData().getTasks();
            Integer currentStep = result.getData().getCurrentStep();
            List<TaskStepVO> taskStepVOList = tasks.stream().map(task -> {
                TaskStepVO taskStepVO = new TaskStepVO();
                taskStepVO.setStep(task.getTaskStep());
                taskStepVO.setTaskName(task.getTaskName());
                taskStepVO.setRoleName(task.getRoleName());
                List<Integer> statusList = Arrays.asList(
                        MerchantCouponStatusEnum.WAIT_EXECUTE.getCode(),
                        MerchantCouponStatusEnum.EXECUTING.getCode(),
                        MerchantCouponStatusEnum.STOP.getCode(),
                        MerchantCouponStatusEnum.CANCEL.getCode(),
                        MerchantCouponStatusEnum.FINISH.getCode()
                );
                if (StringUtils.isBlank(merchantCouponDO.getTaskId()) && statusList.contains(merchantCouponDO.getStatus())) {
                    taskStepVO.setIsExecute(CommonBooleanEnum.YES.getCode());
                } else {
                    taskStepVO.setIsExecute(currentStep >= task.getTaskStep() ? CommonBooleanEnum.YES.getCode() : CommonBooleanEnum.NO.getCode());
                }
                return taskStepVO;
            }).collect(Collectors.toList());
            response.setTaskSteps(taskStepVOList);
        }

        return Wrapper.success(response);
    }

    @Override
    public Wrapper<MerchantCouponGrantResponse> getGrantMerchantCoupon(CommonIdReq request, UserLoginCacheDTO loginUser) {
        MerchantCouponDO merchantCouponDO = merchantCouponRepository.findById(request.getId()).orElse(null);
        if (Objects.isNull(merchantCouponDO)) {
            return Wrapper.fail(ResponseCode.MARKETING_RECORDS_DONT_EXIST);
        }

        if (!isBelongCurrentMember(loginUser, merchantCouponDO.getMemberId(), merchantCouponDO.getRoleId())) {
            return Wrapper.fail(ResponseCode.MARKETING_RECORDS_DONT_EXIST);
        }

        // 增加拓展详情
        MerchantCouponGrantResponse response = new MerchantCouponGrantResponse();
        response.setId(merchantCouponDO.getId());
        response.setName(merchantCouponDO.getName());
        response.setType(merchantCouponDO.getType());
        response.setTypeName(MerchantCouponTypeEnum.getCodeMessage(merchantCouponDO.getType()));
        response.setReleaseTimeStart(merchantCouponDO.getReleaseTimeStart());
        response.setReleaseTimeEnd(merchantCouponDO.getReleaseTimeEnd());
        response.setDenomination(merchantCouponDO.getDenomination());
        response.setQuantity(merchantCouponDO.getQuantity());
        response.setGetWay(merchantCouponDO.getGetWay());
        response.setGetWayName(MerchantCouponGetWayEnum.getCodeMessage(merchantCouponDO.getGetWay()));
        response.setConditionGetTotal(merchantCouponDO.getConditionGetTotal());
        response.setConditionGetDay(merchantCouponDO.getConditionGetDay());
        response.setEffectiveType(merchantCouponDO.getEffectiveType());
        response.setEffectiveTimeStart(merchantCouponDO.getEffectiveTimeStart());
        response.setEffectiveTimeEnd(merchantCouponDO.getEffectiveTimeEnd());
        response.setInvalidDay(merchantCouponDO.getInvalidDay());
        response.setUseConditionMoney(merchantCouponDO.getUseConditionMoney());
        response.setUseConditionDesc(merchantCouponDO.getUseConditionDesc());
        response.setStatus(merchantCouponDO.getStatus());
        response.setStatusName(MerchantCouponStatusEnum.getCodeMessage(merchantCouponDO.getStatus()));
        response.setCreateTime(merchantCouponDO.getCreateTime());
        response.setSuitableMemberLevelTypes(baseCouponRuleService.listMemberLevelId(BelongTypeEnum.MERCHANT, merchantCouponDO.getId()));

        List<MerchantCouponDetailDO> detailDOList = merchantCouponDetailRepository.findAllByCouponId(merchantCouponDO.getId());
        List<MemberAndRoleIdVO> memberList = detailDOList.stream().map(detail -> new MemberAndRoleIdVO(detail.getSubMemberId(), detail.getSubRoleId())).collect(Collectors.toList());
        response.setMemberList(memberList);

        return Wrapper.success(response);
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public Wrapper<Void> addMerchantCoupon(MerchantCouponAddRequest request, UserLoginCacheDTO loginUser) {
        // 参数校验
        Wrapper<Void> checkWrapper = this.checkMerchantCouponParam(request);
        if (ResponseCode.SUCCESS.getCode() != checkWrapper.getCode()) {
            return Wrapper.fail(checkWrapper.getCode(), checkWrapper.getMessage());
        }

        // 查询商城数据
        Wrapper<List<ShopVO>> shopWrapper = platformManageService.shopByIdList(request.getSuitableMallTypes());
        if (ResponseCode.SUCCESS.getCode() != shopWrapper.getCode()) {
            return Wrapper.fail(shopWrapper.getCode(), shopWrapper.getMessage());
        }
        List<ShopVO> shopVOList = shopWrapper.getData();

        // 查询适用会员等级
        List<MemberFeignLevelConfigVO> memberFeignLevelConfigVOList = Collections.emptyList();
        if (request.getSuitableMemberTypes().contains(AbilitySuitableMemberEnum.NEW_MEMBER.getCode())
                || request.getSuitableMemberTypes().contains(AbilitySuitableMemberEnum.OLD_MEMBER.getCode())) {
            // 有无勾选适用会员等级
            List<Long> memberLevelConfigIds = request.getSuitableMemberLevelTypes();
            if (!CollectionUtils.isEmpty(memberLevelConfigIds)) {
                Wrapper<List<MemberFeignLevelConfigVO>> memberLevelConfigWrapper = memberFeignService.getMemberLevelConfigBatch(request.getSuitableMemberLevelTypes());
                if (ResponseCode.SUCCESS.getCode() != memberLevelConfigWrapper.getCode()) {
                    return Wrapper.fail(memberLevelConfigWrapper.getCode(), memberLevelConfigWrapper.getMessage());
                }
                memberFeignLevelConfigVOList = memberLevelConfigWrapper.getData();
            }
        }

        // 适用品类, 品牌, 商品
        List<CustomerCategoryResponse> categoryResponseList = new ArrayList<>();
        List<BrandResponse> brandResponseList = new ArrayList<>();
        List<SuitableCommoditySkuVO> suitableCommoditySkuList = new ArrayList<>();
        if (MerchantCouponTypeEnum.CATEGORY.getCode().equals(request.getType())) {
            // 提交的多级品类集合
            Wrapper<List<CustomerCategoryResponse>> categoryWrapper = baseCouponGoodsService.queryMerchantCouponCategory(request.getSuitableCategoryList());
            if (ResponseCode.SUCCESS.getCode() != categoryWrapper.getCode()) {
                return Wrapper.fail(categoryWrapper.getCode(), categoryWrapper.getMessage());
            }
            categoryResponseList = categoryWrapper.getData();
        } else if (MerchantCouponTypeEnum.BRAND.getCode().equals(request.getType())) {
            // 提交的品牌数据
            Wrapper<List<BrandResponse>> brandWrapper = baseCouponGoodsService.queryMerchantCouponBrand(request.getSuitableBrandList());
            if (ResponseCode.SUCCESS.getCode() != brandWrapper.getCode()) {
                return Wrapper.fail(brandWrapper.getCode(), brandWrapper.getMessage());
            }
            brandResponseList = brandWrapper.getData();
        } else if (MerchantCouponTypeEnum.COMMODITY.getCode().equals(request.getType())) {
            // 商品不能重复
            suitableCommoditySkuList = request.getSuitableCommoditySkuList();
            if (!suitableCommoditySkuList.stream().map(SuitableCommoditySkuVO::getId).allMatch(new HashSet<>()::add)) {
                return Wrapper.fail(ResponseCode.MARKETING_COUPON_COMMODITY_NO_REPEAT);
            }
        } else if (MerchantCouponTypeEnum.ZERO_DISCOUNT.getCode().equals(request.getType())) {
            // 商品只能选择一个
            suitableCommoditySkuList = request.getSuitableCommoditySkuList();
            if (suitableCommoditySkuList.size() > 1) {
                return Wrapper.fail(ResponseCode.MARKETING_COUPON_COMMODITY_MUST_ONE);
            }
        }

        MerchantCouponDO merchantCouponDO = new MerchantCouponDO();
        merchantCouponDO.setName(request.getName());
        merchantCouponDO.setType(request.getType());
        merchantCouponDO.setReleaseTimeStart(request.getReleaseTimeStart());
        merchantCouponDO.setReleaseTimeEnd(request.getReleaseTimeEnd());
        merchantCouponDO.setDenomination(request.getDenomination());
        merchantCouponDO.setQuantity(request.getQuantity());
        merchantCouponDO.setGetWay(request.getGetWay());
        merchantCouponDO.setEffectiveType(request.getEffectiveType());
        merchantCouponDO.setUseConditionMoney(request.getUseConditionMoney());
        merchantCouponDO.setUseConditionDesc(request.getUseConditionDesc());
        // 适用用户
        merchantCouponDO.setSuitableUser(SuitableFieldComponent.generateCouponSuitableUser(request.getSuitableMemberTypes()));
        merchantCouponDO.setMemberId(loginUser.getMemberId());
        merchantCouponDO.setRoleId(loginUser.getMemberRoleId());
        merchantCouponDO.setMemberName(loginUser.getCompany());
        merchantCouponDO.setCreateTime(System.currentTimeMillis());
        // 前台用户领券
        if (MerchantCouponGetWayEnum.FRONT.getCode().equals(request.getGetWay())) {
            merchantCouponDO.setConditionGetTotal(request.getConditionGetTotal());
            merchantCouponDO.setConditionGetDay(request.getConditionGetDay());
        }
        // 券有效时间
        if (MerchantCouponEffectiveTypeEnum.FIXED.getCode().equals(request.getEffectiveType())) {
            merchantCouponDO.setEffectiveTimeStart(request.getEffectiveTimeStart());
            merchantCouponDO.setEffectiveTimeEnd(request.getEffectiveTimeEnd());
        } else {
            merchantCouponDO.setInvalidDay(request.getInvalidDay());
        }
        merchantCouponRepository.saveAndFlush(merchantCouponDO);

        // 适用品类, 品牌, 商品
        if (MerchantCouponTypeEnum.CATEGORY.getCode().equals(request.getType())) {
            baseCouponGoodsService.saveMerchantCouponCategory(merchantCouponDO.getId(), request.getSuitableCategoryList(), categoryResponseList);
        } else if (MerchantCouponTypeEnum.BRAND.getCode().equals(request.getType())) {
            baseCouponGoodsService.saveMerchantCouponBrand(merchantCouponDO.getId(), request.getSuitableBrandList(), brandResponseList);
        } else if (MerchantCouponTypeEnum.COMMODITY.getCode().equals(request.getType())) {
            baseCouponGoodsService.saveMerchantCouponGoods(loginUser, merchantCouponDO.getId(), suitableCommoditySkuList);
        } else if (MerchantCouponTypeEnum.ZERO_DISCOUNT.getCode().equals(request.getType())) {
            baseCouponGoodsService.saveMerchantCouponGoods(loginUser, merchantCouponDO.getId(), suitableCommoditySkuList);
        }

        if (request.getSuitableMemberTypes().contains(AbilitySuitableMemberEnum.NEW_MEMBER.getCode())
                || request.getSuitableMemberTypes().contains(AbilitySuitableMemberEnum.OLD_MEMBER.getCode())) {
            // 会员等级
            baseCouponRuleService.saveMemberLevel(BelongTypeEnum.MERCHANT, merchantCouponDO.getId(), memberFeignLevelConfigVOList);
        }

        // 商城
        baseCouponRuleService.saveShop(BelongTypeEnum.MERCHANT, merchantCouponDO.getId(), shopVOList);

        TaskStartVO taskStartVO = new TaskStartVO();
        taskStartVO.setProcessKey(MarketingConstants.merchant_coupon_key);
        taskStartVO.setMemberId(loginUser.getMemberId());
        taskStartVO.setRoleId(loginUser.getMemberRoleId());
        taskStartVO.setDataId(merchantCouponDO.getId());

        Wrapper<SimpleTaskCompleteVO> result = processFeignService.startSimpleProcess(taskStartVO);
        if (result.getCode() != ResponseCode.SUCCESS.getCode()) {
            log.error("商家优惠券新增, 调用工作流失败: {}", result.getMessage());
            throw new BusinessException(ResponseCode.SERVICE_WORKFLOW_ERROR);
        }

        merchantCouponDO.setStatus(result.getData().getStatus());
        merchantCouponDO.setTaskId(result.getData().getTaskId());
        merchantCouponRepository.saveAndFlush(merchantCouponDO);

        return Wrapper.success();
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public Wrapper<Void> updateMerchantCoupon(MerchantCouponUpdateRequest request, UserLoginCacheDTO loginUser) {
        // 参数校验
        Wrapper<Void> checkWrapper = this.checkMerchantCouponParam(request);
        if (ResponseCode.SUCCESS.getCode() != checkWrapper.getCode()) {
            return Wrapper.fail(checkWrapper.getCode(), checkWrapper.getMessage());
        }

        MerchantCouponDO merchantCouponDO = merchantCouponRepository.findById(request.getId()).orElse(null);
        if (Objects.isNull(merchantCouponDO)) {
            return Wrapper.fail(ResponseCode.MARKETING_RECORDS_DONT_EXIST);
        }

        if (!isBelongCurrentMember(loginUser, merchantCouponDO.getMemberId(), merchantCouponDO.getRoleId())) {
            return Wrapper.fail(ResponseCode.MARKETING_RECORDS_DONT_EXIST);
        }

        // 校验状态
        List<Integer> statusList = Arrays.asList(MerchantCouponStatusEnum.WAIT_SUBMIT_AUDIT.getCode(), MerchantCouponStatusEnum.WAIT_AUDIT_1_REJECT.getCode(), MerchantCouponStatusEnum.WAIT_AUDIT_2_REJECT.getCode());
        if (!statusList.contains(merchantCouponDO.getStatus())) {
            return Wrapper.fail(ResponseCode.MARKETING_DATA_STATUS_INCORRECT_OPERATE_INVALID);
        }

        // 查询商城数据
        Wrapper<List<ShopVO>> shopWrapper = platformManageService.shopByIdList(request.getSuitableMallTypes());
        if (ResponseCode.SUCCESS.getCode() != shopWrapper.getCode()) {
            return Wrapper.fail(shopWrapper.getCode(), shopWrapper.getMessage());
        }
        List<ShopVO> shopVOList = shopWrapper.getData();

        // 查询适用会员等级
        List<MemberFeignLevelConfigVO> memberFeignLevelConfigVOList = Collections.emptyList();
        if (request.getSuitableMemberTypes().contains(AbilitySuitableMemberEnum.NEW_MEMBER.getCode())
                || request.getSuitableMemberTypes().contains(AbilitySuitableMemberEnum.OLD_MEMBER.getCode())) {
            // 有无勾选适用会员等级
            List<Long> memberLevelConfigIds = request.getSuitableMemberLevelTypes();
            if (!CollectionUtils.isEmpty(memberLevelConfigIds)) {
                Wrapper<List<MemberFeignLevelConfigVO>> memberLevelConfigWrapper = memberFeignService.getMemberLevelConfigBatch(request.getSuitableMemberLevelTypes());
                if (ResponseCode.SUCCESS.getCode() != memberLevelConfigWrapper.getCode()) {
                    return Wrapper.fail(memberLevelConfigWrapper.getCode(), memberLevelConfigWrapper.getMessage());
                }
                memberFeignLevelConfigVOList = memberLevelConfigWrapper.getData();
            }
        }

        // 适用品类, 品牌, 商品
        List<CustomerCategoryResponse> categoryResponseList = new ArrayList<>();
        List<BrandResponse> brandResponseList = new ArrayList<>();
        List<SuitableCommoditySkuVO> suitableCommoditySkuList = new ArrayList<>();
        if (MerchantCouponTypeEnum.CATEGORY.getCode().equals(request.getType())) {
            // 提交的多级品类集合
            Wrapper<List<CustomerCategoryResponse>> categoryWrapper = baseCouponGoodsService.queryMerchantCouponCategory(request.getSuitableCategoryList());
            if (ResponseCode.SUCCESS.getCode() != categoryWrapper.getCode()) {
                return Wrapper.fail(categoryWrapper.getCode(), categoryWrapper.getMessage());
            }
            categoryResponseList = categoryWrapper.getData();
        } else if (MerchantCouponTypeEnum.BRAND.getCode().equals(request.getType())) {
            // 提交的品牌数据
            Wrapper<List<BrandResponse>> brandWrapper = baseCouponGoodsService.queryMerchantCouponBrand(request.getSuitableBrandList());
            if (ResponseCode.SUCCESS.getCode() != brandWrapper.getCode()) {
                return Wrapper.fail(brandWrapper.getCode(), brandWrapper.getMessage());
            }
            brandResponseList = brandWrapper.getData();
        } else if (MerchantCouponTypeEnum.COMMODITY.getCode().equals(request.getType())) {
            // 商品不能重复
            suitableCommoditySkuList = request.getSuitableCommoditySkuList();
            if (!suitableCommoditySkuList.stream().map(SuitableCommoditySkuVO::getCommodityId).allMatch(new HashSet<>()::add)) {
                return Wrapper.fail(ResponseCode.MARKETING_COUPON_COMMODITY_NO_REPEAT);
            }
        } else if (MerchantCouponTypeEnum.ZERO_DISCOUNT.getCode().equals(request.getType())) {
            // 商品只能选择一个
            suitableCommoditySkuList = request.getSuitableCommoditySkuList();
            if (suitableCommoditySkuList.size() > 1) {
                return Wrapper.fail(ResponseCode.MARKETING_COUPON_COMMODITY_MUST_ONE);
            }
        }

        // 拒绝状态修改后为待提交
        List<Integer> rejectStatusList = Arrays.asList(MerchantCouponStatusEnum.WAIT_AUDIT_1_REJECT.getCode(), MerchantCouponStatusEnum.WAIT_AUDIT_2_REJECT.getCode());
        if (rejectStatusList.contains(merchantCouponDO.getStatus())) {
            merchantCouponDO.setStatus(MerchantCouponStatusEnum.WAIT_SUBMIT_AUDIT.getCode());
        }

        merchantCouponDO.setName(request.getName());
        merchantCouponDO.setType(request.getType());
        merchantCouponDO.setReleaseTimeStart(request.getReleaseTimeStart());
        merchantCouponDO.setReleaseTimeEnd(request.getReleaseTimeEnd());
        merchantCouponDO.setDenomination(request.getDenomination());
        merchantCouponDO.setQuantity(request.getQuantity());
        merchantCouponDO.setGetWay(request.getGetWay());
        merchantCouponDO.setEffectiveType(request.getEffectiveType());
        merchantCouponDO.setUseConditionMoney(request.getUseConditionMoney());
        merchantCouponDO.setUseConditionDesc(request.getUseConditionDesc());

        // 前台用户领券
        if (MerchantCouponGetWayEnum.FRONT.getCode().equals(request.getGetWay())) {
            merchantCouponDO.setConditionGetTotal(request.getConditionGetTotal());
            merchantCouponDO.setConditionGetDay(request.getConditionGetDay());
        } else {
            merchantCouponDO.setConditionGetTotal(null);
            merchantCouponDO.setConditionGetDay(null);
        }
        // 券有效时间
        if (MerchantCouponEffectiveTypeEnum.FIXED.getCode().equals(request.getEffectiveType())) {
            merchantCouponDO.setEffectiveTimeStart(request.getEffectiveTimeStart());
            merchantCouponDO.setEffectiveTimeEnd(request.getEffectiveTimeEnd());
            merchantCouponDO.setInvalidDay(null);
        } else {
            merchantCouponDO.setInvalidDay(request.getInvalidDay());
            merchantCouponDO.setEffectiveTimeStart(null);
            merchantCouponDO.setEffectiveTimeEnd(null);
        }

        if (Arrays.asList(MerchantCouponStatusEnum.WAIT_AUDIT_1.getCode(), MerchantCouponStatusEnum.WAIT_AUDIT_2.getCode()).contains(merchantCouponDO.getStatus())) {
            merchantCouponDO.setStatus(MerchantCouponStatusEnum.WAIT_SUBMIT_AUDIT.getCode());
        }

        // 商城
        baseCouponRuleService.deleteShop(BelongTypeEnum.MERCHANT, merchantCouponDO.getId());
        baseCouponRuleService.saveShop(BelongTypeEnum.MERCHANT, merchantCouponDO.getId(), shopVOList);

        // 会员等级
        baseCouponRuleService.existsAndDeleteMemberLevel(BelongTypeEnum.MERCHANT, merchantCouponDO.getId());
        if (request.getSuitableMemberTypes().contains(AbilitySuitableMemberEnum.NEW_MEMBER.getCode())
                || request.getSuitableMemberTypes().contains(AbilitySuitableMemberEnum.OLD_MEMBER.getCode())) {
            // 会员等级
            baseCouponRuleService.saveMemberLevel(BelongTypeEnum.MERCHANT, merchantCouponDO.getId(), memberFeignLevelConfigVOList);
        }

        // 适用品类, 品牌, 商品
        if (MerchantCouponTypeEnum.CATEGORY.getCode().equals(request.getType())) {
            // 品类
            baseCouponGoodsService.existsAndDeleteMerchantCouponBrand(merchantCouponDO.getId());
            baseCouponGoodsService.existsAndDeleteMerchantCouponCategory(merchantCouponDO.getId());
            baseCouponGoodsService.existsAndDeleteCouponGoods(BelongTypeEnum.MERCHANT, merchantCouponDO.getId());
            baseCouponGoodsService.saveMerchantCouponCategory(merchantCouponDO.getId(), request.getSuitableCategoryList(), categoryResponseList);
        } else if (MerchantCouponTypeEnum.BRAND.getCode().equals(request.getType())) {
            // 品牌
            baseCouponGoodsService.existsAndDeleteMerchantCouponBrand(merchantCouponDO.getId());
            baseCouponGoodsService.existsAndDeleteMerchantCouponCategory(merchantCouponDO.getId());
            baseCouponGoodsService.existsAndDeleteCouponGoods(BelongTypeEnum.MERCHANT, merchantCouponDO.getId());
            baseCouponGoodsService.saveMerchantCouponBrand(merchantCouponDO.getId(), request.getSuitableBrandList(), brandResponseList);
        } else if (MerchantCouponTypeEnum.COMMODITY.getCode().equals(request.getType())) {
            // 商品
            baseCouponGoodsService.existsAndDeleteMerchantCouponBrand(merchantCouponDO.getId());
            baseCouponGoodsService.existsAndDeleteMerchantCouponCategory(merchantCouponDO.getId());
            baseCouponGoodsService.existsAndDeleteCouponGoods(BelongTypeEnum.MERCHANT, merchantCouponDO.getId());
            baseCouponGoodsService.saveMerchantCouponGoods(loginUser, merchantCouponDO.getId(), suitableCommoditySkuList);
        } else if (MerchantCouponTypeEnum.ZERO_DISCOUNT.getCode().equals(request.getType())) {
            // 0元抵扣
            baseCouponGoodsService.existsAndDeleteMerchantCouponBrand(merchantCouponDO.getId());
            baseCouponGoodsService.existsAndDeleteMerchantCouponCategory(merchantCouponDO.getId());
            baseCouponGoodsService.existsAndDeleteCouponGoods(BelongTypeEnum.MERCHANT, merchantCouponDO.getId());
            baseCouponGoodsService.saveMerchantCouponGoods(loginUser, merchantCouponDO.getId(), suitableCommoditySkuList);
        }

        merchantCouponRepository.saveAndFlush(merchantCouponDO);

        return Wrapper.success();
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public Wrapper<Void> deleteMerchantCoupon(CommonIdsRequest request, UserLoginCacheDTO loginUser) {
        List<MerchantCouponDO> merchantCouponDOList = merchantCouponRepository.findAllById(request.getIds());
        if (CollectionUtils.isEmpty(merchantCouponDOList)) {
            return Wrapper.fail(ResponseCode.MARKETING_RECORDS_DONT_EXIST);
        }

        for (MerchantCouponDO merchantCouponDO : merchantCouponDOList) {
            if (!isBelongCurrentMember(loginUser, merchantCouponDO.getMemberId(), merchantCouponDO.getRoleId())) {
                return Wrapper.fail(ResponseCode.MARKETING_RECORDS_DONT_EXIST);
            }
            if (!MerchantCouponStatusEnum.WAIT_SUBMIT_AUDIT.getCode().equals(merchantCouponDO.getStatus())) {
                return Wrapper.fail(ResponseCode.MARKETING_DATA_STATUS_INCORRECT_OPERATE_INVALID);
            }
        }

        // 删除商城
        shopRepository.deleteByBelongTypeAndCouponIdIn(BelongTypeEnum.MERCHANT.getCode(), request.getIds());
        // 删除会员等级
        memberLevelRepository.deleteByBelongTypeAndCouponIdIn(BelongTypeEnum.MERCHANT.getCode(), request.getIds());
        for (MerchantCouponDO merchantCouponDO : merchantCouponDOList) {
            if (MerchantCouponTypeEnum.CATEGORY.getCode().equals(merchantCouponDO.getType())) {
                categoryRepository.deleteByCouponId(merchantCouponDO.getId());
            } else if (MerchantCouponTypeEnum.BRAND.getCode().equals(merchantCouponDO.getType())) {
                brandRepository.deleteByCouponId(merchantCouponDO.getId());
            } else if (MerchantCouponTypeEnum.COMMODITY.getCode().equals(merchantCouponDO.getType())) {
                goodsRepository.deleteByBelongTypeAndCouponId(BelongTypeEnum.MERCHANT.getCode(), merchantCouponDO.getId());
            }
        }

        merchantCouponRepository.deleteAll(merchantCouponDOList);

        return Wrapper.success();
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public Wrapper<Void> submitAuditMerchantCoupon(CommonIdsRequest request, UserLoginCacheDTO loginUser) {
        List<MerchantCouponDO> merchantCouponDOList = merchantCouponRepository.findAllById(request.getIds());
        if (CollectionUtils.isEmpty(merchantCouponDOList)) {
            return Wrapper.fail(ResponseCode.MARKETING_RECORDS_DONT_EXIST);
        }

        List<MerchantCouponDO> updateList = new ArrayList<>();
        for (MerchantCouponDO merchantCouponDO : merchantCouponDOList) {
            if (!isBelongCurrentMember(loginUser, merchantCouponDO.getMemberId(), merchantCouponDO.getRoleId())) {
                continue;
            }
            if (!MerchantCouponStatusEnum.WAIT_SUBMIT_AUDIT.getCode().equals(merchantCouponDO.getStatus())) {
                continue;
            }
            updateList.add(merchantCouponDO);
        }

        for (MerchantCouponDO merchantCouponDO : updateList) {
            TaskExecuteVO executeVO = new TaskExecuteVO();
            executeVO.setProcessKey(MarketingConstants.merchant_coupon_key);
            executeVO.setTaskId(merchantCouponDO.getTaskId());
            executeVO.setMemberId(loginUser.getMemberId());
            executeVO.setRoleId(loginUser.getMemberRoleId());
            executeVO.setAgree(ProcessTaskStatusEnum.GOTO_NEXT_STEP.getCode());
            executeVO.setDataId(merchantCouponDO.getId());

            // 工作流
            Wrapper<SimpleTaskCompleteVO> result = processFeignService.completeSimpleTask(executeVO);
            if (result.getCode() != ResponseCode.SUCCESS.getCode()) {
                log.error("商家优惠券提交审核,调用工作流失败: {}", result.getMessage());
                throw new BusinessException(ResponseCode.SERVICE_WORKFLOW_ERROR);
            }

            merchantCouponDO.setStatus(result.getData().getStatus());
            merchantCouponDO.setTaskId(result.getData().getTaskId());
            merchantCouponRepository.saveAndFlush(merchantCouponDO);

            // 流转记录
            Integer status = result.getData().getStatus();
            baseCouponRecordService.saveMerchantCouponRecord(loginUser, merchantCouponDO, CouponStrOperateEnum.mc_inner_add.getMessage(), status, MerchantCouponStatusEnum.getCodeMessage(status));
        }

        return Wrapper.success();
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public Wrapper<Void> auditOneMerchantCoupon(CommonAgreeRequest request, UserLoginCacheDTO loginUser) {
        MerchantCouponDO merchantCouponDO = merchantCouponRepository.findById(request.getId()).orElse(null);
        if (Objects.isNull(merchantCouponDO)) {
            return Wrapper.fail(ResponseCode.MARKETING_RECORDS_DONT_EXIST);
        }

        if (!isBelongCurrentMember(loginUser, merchantCouponDO.getMemberId(), merchantCouponDO.getRoleId())) {
            return Wrapper.fail(ResponseCode.MARKETING_RECORDS_DONT_EXIST);
        }

        if (!MerchantCouponStatusEnum.WAIT_AUDIT_1.getCode().equals(merchantCouponDO.getStatus())) {
            return Wrapper.fail(ResponseCode.MARKETING_DATA_STATUS_INCORRECT_OPERATE_INVALID);
        }

        this.baseAuditOneMerchantCoupon(loginUser, Collections.singletonList(merchantCouponDO), request.getAgree(), request.getReason());

        return Wrapper.success();
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public Wrapper<Void> batchAuditOneMerchantCoupon(CommonIdsRequest request, UserLoginCacheDTO loginUser) {
        List<MerchantCouponDO> merchantCouponDOList = merchantCouponRepository.findAllById(request.getIds());
        if (CollectionUtils.isEmpty(merchantCouponDOList)) {
            return Wrapper.fail(ResponseCode.MARKETING_RECORDS_DONT_EXIST);
        }

        for (MerchantCouponDO merchantCouponDO : merchantCouponDOList) {
            if (!isBelongCurrentMember(loginUser, merchantCouponDO.getMemberId(), merchantCouponDO.getRoleId())) {
                return Wrapper.fail(ResponseCode.MARKETING_RECORDS_DONT_EXIST);
            }
            if (!MerchantCouponStatusEnum.WAIT_AUDIT_1.getCode().equals(merchantCouponDO.getStatus())) {
                return Wrapper.fail(ResponseCode.MARKETING_DATA_STATUS_INCORRECT_OPERATE_INVALID);
            }
        }

        this.baseAuditOneMerchantCoupon(loginUser, merchantCouponDOList, ProcessTaskStatusEnum.AGREE.getCode(), "");

        return Wrapper.success();
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public Wrapper<Void> auditTwoMerchantCoupon(CommonAgreeRequest request, UserLoginCacheDTO loginUser) {
        MerchantCouponDO merchantCouponDO = merchantCouponRepository.findById(request.getId()).orElse(null);
        if (Objects.isNull(merchantCouponDO)) {
            return Wrapper.fail(ResponseCode.MARKETING_RECORDS_DONT_EXIST);
        }

        if (!isBelongCurrentMember(loginUser, merchantCouponDO.getMemberId(), merchantCouponDO.getRoleId())) {
            return Wrapper.fail(ResponseCode.MARKETING_RECORDS_DONT_EXIST);
        }

        if (!MerchantCouponStatusEnum.WAIT_AUDIT_2.getCode().equals(merchantCouponDO.getStatus())) {
            return Wrapper.fail(ResponseCode.MARKETING_DATA_STATUS_INCORRECT_OPERATE_INVALID);
        }

        this.baseAuditTwoMerchantCoupon(loginUser, Collections.singletonList(merchantCouponDO), ProcessTaskStatusEnum.AGREE.getCode(), request.getReason());

        return Wrapper.success();
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public Wrapper<Void> batchAuditTwoMerchantCoupon(CommonIdsRequest request, UserLoginCacheDTO loginUser) {
        List<MerchantCouponDO> merchantCouponDOList = merchantCouponRepository.findAllById(request.getIds());
        if (CollectionUtils.isEmpty(merchantCouponDOList)) {
            return Wrapper.fail(ResponseCode.MARKETING_RECORDS_DONT_EXIST);
        }

        for (MerchantCouponDO merchantCouponDO : merchantCouponDOList) {
            if (!isBelongCurrentMember(loginUser, merchantCouponDO.getMemberId(), merchantCouponDO.getRoleId())) {
                return Wrapper.fail(ResponseCode.MARKETING_RECORDS_DONT_EXIST);
            }
            if (!MerchantCouponStatusEnum.WAIT_AUDIT_2.getCode().equals(merchantCouponDO.getStatus())) {
                return Wrapper.fail(ResponseCode.MARKETING_DATA_STATUS_INCORRECT_OPERATE_INVALID);
            }
        }

        this.baseAuditTwoMerchantCoupon(loginUser, merchantCouponDOList, ProcessTaskStatusEnum.AGREE.getCode(), "");

        return Wrapper.success();
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public Wrapper<Void> submitMerchantCoupon(CommonIdsRequest request, UserLoginCacheDTO loginUser) {
        List<MerchantCouponDO> merchantCouponDOList = merchantCouponRepository.findAllById(request.getIds());
        if (CollectionUtils.isEmpty(merchantCouponDOList)) {
            return Wrapper.fail(ResponseCode.MARKETING_RECORDS_DONT_EXIST);
        }

        for (MerchantCouponDO merchantCouponDO : merchantCouponDOList) {
            if (!isBelongCurrentMember(loginUser, merchantCouponDO.getMemberId(), merchantCouponDO.getRoleId())) {
                return Wrapper.fail(ResponseCode.MARKETING_RECORDS_DONT_EXIST);
            }
            if (!MerchantCouponStatusEnum.WAIT_SUBMIT.getCode().equals(merchantCouponDO.getStatus())) {
                return Wrapper.fail(ResponseCode.MARKETING_DATA_STATUS_INCORRECT_OPERATE_INVALID);
            }
        }

        this.baseSubmitMerchantCoupon(loginUser, merchantCouponDOList);

        return Wrapper.success();
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public Wrapper<Void> grantMerchantCoupon(MerchantCouponGrantRequest request, UserLoginCacheDTO loginUser) {
        MerchantCouponDO merchantCouponDO = merchantCouponRepository.findById(request.getId()).orElse(null);
        if (Objects.isNull(merchantCouponDO)) {
            return Wrapper.fail(ResponseCode.MARKETING_RECORDS_DONT_EXIST);
        }

        if (!isBelongCurrentMember(loginUser, merchantCouponDO.getMemberId(), merchantCouponDO.getRoleId())) {
            return Wrapper.fail(ResponseCode.MARKETING_RECORDS_DONT_EXIST);
        }

        Wrapper<Void> merchantCouponWrapper = couponReceiveComponent.grantMerchantCoupon(merchantCouponDO, request.getGrantMembers());
        if (ResponseCode.SUCCESS.getCode() != merchantCouponWrapper.getCode()) {
            return Wrapper.fail(merchantCouponWrapper.getCode(), merchantCouponWrapper.getMessage());
        }

        return Wrapper.success();
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public Wrapper<Void> modificationMerchantCoupon(MerchantCouponModificationRequest request, UserLoginCacheDTO loginUser) {
        long currentTimeMillis = System.currentTimeMillis();
        // 发放时间
        Wrapper<Void> checkReleaseTimeWrapper = this.checkReleaseTime(currentTimeMillis, request.getReleaseTimeStart(), request.getReleaseTimeEnd());
        if (ResponseCode.SUCCESS.getCode() != checkReleaseTimeWrapper.getCode()) {
            return checkReleaseTimeWrapper;
        }

        MerchantCouponDO merchantCouponDO = merchantCouponRepository.findById(request.getId()).orElse(null);
        if (Objects.isNull(merchantCouponDO)) {
            return Wrapper.fail(ResponseCode.MARKETING_RECORDS_DONT_EXIST);
        }

        if (!isBelongCurrentMember(loginUser, merchantCouponDO.getMemberId(), merchantCouponDO.getRoleId())) {
            return Wrapper.fail(ResponseCode.MARKETING_RECORDS_DONT_EXIST);
        }

        // 发券数量只能修改多, 不能修改少
        if (merchantCouponDO.getQuantity() > request.getQuantity()) {
            return Wrapper.fail(ResponseCode.MARKETING_COUPON_QUANTITY_GRATER_THEN_OLD_ERROR);
        }

        List<Integer> statusList = Arrays.asList(MerchantCouponStatusEnum.WAIT_EXECUTE.getCode(), MerchantCouponStatusEnum.EXECUTING.getCode(), MerchantCouponStatusEnum.STOP.getCode());
        if (!statusList.contains(merchantCouponDO.getStatus())) {
            return Wrapper.fail(ResponseCode.MARKETING_DATA_STATUS_INCORRECT_OPERATE_INVALID);
        }

        merchantCouponDO.setStatus(MerchantCouponStatusEnum.WAIT_EXECUTE.getCode());
        merchantCouponDO.setReleaseTimeStart(request.getReleaseTimeStart());
        merchantCouponDO.setReleaseTimeEnd(request.getReleaseTimeEnd());
        merchantCouponDO.setQuantity(request.getQuantity());
        merchantCouponRepository.saveAndFlush(merchantCouponDO);

        // 状态
        if (request.getReleaseTimeStart() > currentTimeMillis) {
            // 定时发券开始
            scheduleFeignService.createMcCouponReleaseStartTask(loginUser, merchantCouponDO);

            // 定时发券结束
            scheduleFeignService.createMcCouponReleaseEndTask(loginUser, merchantCouponDO);
        } else if (request.getReleaseTimeStart() <= currentTimeMillis
                && request.getReleaseTimeEnd() >= currentTimeMillis) {

            merchantCouponDO.setStatus(MerchantCouponStatusEnum.EXECUTING.getCode());
            merchantCouponRepository.saveAndFlush(merchantCouponDO);

            // 定时发券结束
            scheduleFeignService.createMcCouponReleaseEndTask(loginUser, merchantCouponDO);
        }

        return Wrapper.success();
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public Wrapper<Void> stopMerchantCoupon(MerchantCouponOperationRequest request, UserLoginCacheDTO loginUser) {
        MerchantCouponDO merchantCouponDO = merchantCouponRepository.findById(request.getId()).orElse(null);
        if (Objects.isNull(merchantCouponDO)) {
            return Wrapper.fail(ResponseCode.MARKETING_RECORDS_DONT_EXIST);
        }

        if (!isBelongCurrentMember(loginUser, merchantCouponDO.getMemberId(), merchantCouponDO.getRoleId())) {
            return Wrapper.fail(ResponseCode.MARKETING_RECORDS_DONT_EXIST);
        }

        if (!MerchantCouponStatusEnum.EXECUTING.getCode().equals(merchantCouponDO.getStatus())) {
            return Wrapper.fail(ResponseCode.MARKETING_DATA_STATUS_INCORRECT_OPERATE_INVALID);
        }

        merchantCouponDO.setStatus(MerchantCouponStatusEnum.STOP.getCode());
        merchantCouponRepository.saveAndFlush(merchantCouponDO);

        // 流转记录
        baseCouponRecordService.saveMerchantCouponRecord(loginUser, merchantCouponDO, CouponStrOperateEnum.mc_inner_stop.getMessage(), MerchantCouponStatusEnum.STOP.getCode(), MerchantCouponStatusEnum.STOP.getMessage());

        return Wrapper.success();
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public Wrapper<Void> restartMerchantCoupon(MerchantCouponOperationRequest request, UserLoginCacheDTO loginUser) {
        long currentTimeMillis = System.currentTimeMillis();
        MerchantCouponDO merchantCouponDO = merchantCouponRepository.findById(request.getId()).orElse(null);
        if (Objects.isNull(merchantCouponDO)) {
            return Wrapper.fail(ResponseCode.MARKETING_RECORDS_DONT_EXIST);
        }

        if (!isBelongCurrentMember(loginUser, merchantCouponDO.getMemberId(), merchantCouponDO.getRoleId())) {
            return Wrapper.fail(ResponseCode.MARKETING_RECORDS_DONT_EXIST);
        }

        if (!MerchantCouponStatusEnum.STOP.getCode().equals(merchantCouponDO.getStatus())) {
            return Wrapper.fail(ResponseCode.MARKETING_DATA_STATUS_INCORRECT_OPERATE_INVALID);
        }

        if (currentTimeMillis >= merchantCouponDO.getReleaseTimeEnd()) {
            return Wrapper.fail(ResponseCode.MARKETING_COUPON_RELEASE_START_TIME_ERROR);
        }

        merchantCouponDO.setStatus(MerchantCouponStatusEnum.EXECUTING.getCode());
        merchantCouponRepository.saveAndFlush(merchantCouponDO);

        // 流转记录
        baseCouponRecordService.saveMerchantCouponRecord(loginUser, merchantCouponDO, CouponStrOperateEnum.mc_inner_start.getMessage(), MerchantCouponStatusEnum.EXECUTING.getCode(), MerchantCouponStatusEnum.EXECUTING.getMessage());

        return Wrapper.success();
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public Wrapper<Void> cancelMerchantCoupon(MerchantCouponOperationRequest request, UserLoginCacheDTO loginUser) {
        MerchantCouponDO merchantCouponDO = merchantCouponRepository.findById(request.getId()).orElse(null);
        if (Objects.isNull(merchantCouponDO)) {
            return Wrapper.fail(ResponseCode.MARKETING_RECORDS_DONT_EXIST);
        }

        if (!isBelongCurrentMember(loginUser, merchantCouponDO.getMemberId(), merchantCouponDO.getRoleId())) {
            return Wrapper.fail(ResponseCode.MARKETING_RECORDS_DONT_EXIST);
        }

        if (!MerchantCouponStatusEnum.WAIT_EXECUTE.getCode().equals(merchantCouponDO.getStatus())) {
            return Wrapper.fail(ResponseCode.MARKETING_DATA_STATUS_INCORRECT_OPERATE_INVALID);
        }

        merchantCouponDO.setStatus(MerchantCouponStatusEnum.CANCEL.getCode());
        merchantCouponRepository.saveAndFlush(merchantCouponDO);

        // 流转记录
        baseCouponRecordService.saveMerchantCouponRecord(loginUser, merchantCouponDO, CouponStrOperateEnum.mc_inner_cancel.getMessage(), MerchantCouponStatusEnum.CANCEL.getCode(), MerchantCouponStatusEnum.CANCEL.getMessage());

        return Wrapper.success();
    }

    @Override
    public Wrapper<MerchantCouponDetailConditionResponse> getExecuteMerchantCouponDetailCondition(CommonIdReq request) {
        MerchantCouponDetailConditionResponse response = new MerchantCouponDetailConditionResponse();

        // 商城下拉框
        Wrapper<List<ShopVO>> listWrapper = platformManageService.shopAll();
        if (ResponseCode.SUCCESS.getCode() == listWrapper.getCode()) {
            List<SelectItemVO> shopIdList = listWrapper.getData().stream().map(shop -> new SelectItemVO(shop.getId().intValue(), shop.getName())).collect(Collectors.toList());
            response.setShopList(shopIdList);
        }

        // 适用会员下拉框
        List<SelectItemVO> suitableMemberTypeList = Stream.of(AbilitySuitableMemberEnum.values()).map(ageType -> new SelectItemVO(ageType.getCode(), ageType.getMessage())).collect(Collectors.toList());
        response.setSuitableMemberTypeList(suitableMemberTypeList);

        // 券状态下拉框
        List<SelectItemVO> statusList = Stream.of(MerchantCouponDetailStatusEnum.values()).map(ageType -> new SelectItemVO(ageType.getCode(), ageType.getMessage())).collect(Collectors.toList());
        response.setStatusList(statusList);

        return Wrapper.success(response);
    }

    @Override
    public Wrapper<PageData<MerchantCouponDetailPageResponse>> pageExecuteMerchantCouponDetail(MerchantCouponDetailPageRequest request, UserLoginCacheDTO loginUser) {
        MerchantCouponDO merchantCouponDO = merchantCouponRepository.findById(request.getCouponId()).orElse(null);
        if (Objects.isNull(merchantCouponDO)) {
            return Wrapper.fail(ResponseCode.MARKETING_RECORDS_DONT_EXIST);
        }

        if (!isBelongCurrentMember(loginUser, merchantCouponDO.getMemberId(), merchantCouponDO.getRoleId())) {
            return Wrapper.fail(ResponseCode.MARKETING_RECORDS_DONT_EXIST);
        }

        Pageable page = PageRequest.of(request.getCurrent() - 1, request.getPageSize(), Sort.by("id").descending());
        Page<MerchantCouponDetailDO> pageList = merchantCouponDetailRepository.findAll((Specification<MerchantCouponDetailDO>) (root, query, cb) -> {
            List<Predicate> predicateList = new ArrayList<>();

            predicateList.add(cb.equal(root.get("coupon").get("id"), request.getCouponId()));

            if (StringUtils.isNotEmpty(request.getCode())) {
                predicateList.add(cb.equal(root.get("code"), request.getCode()));
            }

            if (Objects.nonNull(request.getStatus())) {
                predicateList.add(cb.equal(root.get("status"), request.getStatus()));
            }

            if (Objects.nonNull(request.getCreateTimeStart())) {
                predicateList.add(cb.greaterThanOrEqualTo(root.get("createTime"), request.getCreateTimeStart()));
            }

            if (Objects.nonNull(request.getCreateTimeEnd())) {
                predicateList.add(cb.lessThanOrEqualTo(root.get("createTime"), request.getCreateTimeEnd()));
            }

            if (StringUtils.isNotEmpty(request.getMemberName())) {
                predicateList.add(cb.lessThanOrEqualTo(root.get("subMemberName"), request.getMemberName()));
            }

            if (Objects.nonNull(request.getSuitableMemberType())) {
                predicateList.add(cb.equal(root.get("suitableMemberType"), request.getSuitableMemberType()));
            }

            if (Objects.nonNull(request.getUseTimeStart())) {
                predicateList.add(cb.greaterThanOrEqualTo(root.get("useTime"), request.getUseTimeStart()));
            }

            if (Objects.nonNull(request.getUseTimeEnd())) {
                predicateList.add(cb.lessThanOrEqualTo(root.get("useTime"), request.getUseTimeEnd()));
            }

            if (Objects.nonNull(request.getOrderNo())) {
                predicateList.add(cb.lessThanOrEqualTo(root.get("orderNo"), request.getOrderNo()));
            }

            if (Objects.nonNull(request.getShopId())) {
                predicateList.add(cb.lessThanOrEqualTo(root.get("shopId"), request.getShopId()));
            }

            Predicate[] p = new Predicate[predicateList.size()];
            return query.where(predicateList.toArray(p)).getRestriction();
        }, page);

        List<String> orderNoList = pageList.stream().map(o -> o.getOrderNo()).collect(Collectors.toList());
        Map<String, OrderAfterSaleStatusVO> orderInfoMap = orderFeignService.getOrderInfoMap(orderNoList);
        List<MerchantCouponDetailPageResponse> resultList = pageList.stream().map(detail -> {
            MerchantCouponDetailPageResponse response = new MerchantCouponDetailPageResponse();
            response.setId(detail.getId());
            response.setMerchantCouponId(detail.getCoupon().getId());
            response.setCode(detail.getCode());
            response.setStatus(detail.getStatus());
            response.setStatusName(PlatformCouponDetailStatusEnum.getCodeMessage(detail.getStatus()));
            response.setSubMemberId(detail.getSubMemberId());
            response.setSubRoleId(detail.getSubRoleId());
            response.setSubMemberName(detail.getSubMemberName());
            response.setSuitableMemberTypeName(AbilitySuitableMemberEnum.getCodeMessage(detail.getSuitableMemberType()));
            response.setCreateTime(detail.getCreateTime());
            response.setValidTimeStart(detail.getValidTimeStart());
            response.setValidTimeEnd(detail.getValidTimeEnd());
            response.setOrderNo(detail.getOrderNo());
            response.setUseTime(detail.getUseTime());
            response.setShopName(detail.getShopName());
            response.setAmount(detail.getAmount());
            response.setBuyerMemberName(detail.getBuyerMemberName());
            response.setOrderStatusName("");
            if(orderInfoMap!=null&& org.springframework.util.StringUtils.hasLength(detail.getOrderNo())){
                OrderAfterSaleStatusVO orderAfterSaleStatusVO = orderInfoMap.get(detail.getOrderNo());
                if(orderAfterSaleStatusVO!=null){
                    response.setOrderStatusName(orderAfterSaleStatusVO.getOuterStatusName());
                }
            }
            return response;
        }).collect(Collectors.toList());
        return Wrapper.success(new PageData<>(pageList.getTotalElements(), resultList));
    }

    @Override
    public Wrapper<List<SelectItemVO>> selectSubsidiaryCouponCondition() {
        // 非0元优惠券
        List<SelectItemVO> statusVOList = Stream.of(MerchantCouponTypeEnum.values())
                .filter(e ->!MerchantCouponTypeEnum.getNotSupportType().contains(e.getCode()))
                .map(e -> {
                    SelectItemVO response = new SelectItemVO();
                    response.setValue(e.getCode());
                    response.setName(e.getMessage());
                    return response;
                }).collect(Collectors.toList());
        return Wrapper.success(statusVOList);
    }

    @Override
    public Wrapper<PageData<ActivityGoodsCouponResponse>> selectSubsidiaryCouponList(ActivityMerchantSubsidiaryCouponRequest request, UserLoginCacheDTO loginUser) {
        long currentTimeMillis = System.currentTimeMillis();
        // 非0元购买抵扣券
        List<Integer> typeList = Arrays.asList(MerchantCouponTypeEnum.COMMON.getCode(),
                MerchantCouponTypeEnum.CATEGORY.getCode(),
                MerchantCouponTypeEnum.BRAND.getCode(),
                MerchantCouponTypeEnum.COMMODITY.getCode());


        Pageable page = PageRequest.of(request.getCurrent() - 1, request.getPageSize(), Sort.by("releaseTimeStart").descending());
        Page<MerchantCouponDO> pageList = merchantCouponRepository.findAll((Specification<MerchantCouponDO>) (root, query, cb) -> {
            List<Predicate> predicateList = new ArrayList<>();

            predicateList.add(cb.equal(root.get("memberId"), loginUser.getMemberId()));
            predicateList.add(cb.equal(root.get("roleId"), loginUser.getMemberRoleId()));
            // 营销活动用券
            predicateList.add(cb.equal(root.get("getWay"), MerchantCouponGetWayEnum.MARKETING.getCode()));
            predicateList.add(cb.and(root.get("type").in(typeList)));

            // 当前时间在发券时间内
            predicateList.add(cb.lessThanOrEqualTo(root.get("releaseTimeStart"), currentTimeMillis));
            predicateList.add(cb.greaterThanOrEqualTo(root.get("releaseTimeEnd"), currentTimeMillis));

            if (Objects.nonNull(request.getId())) {
                predicateList.add(cb.equal(root.get("id"), request.getId()));
            }

            if (Objects.nonNull(request.getType())) {
                predicateList.add(cb.equal(root.get("type"), request.getType()));
            }

            if (Objects.nonNull(request.getName())) {
                predicateList.add(cb.equal(root.get("name"), request.getName()));
            }

            Predicate[] p = new Predicate[predicateList.size()];
            return query.where(predicateList.toArray(p)).getRestriction();
        }, page);

        List<ActivityGoodsCouponResponse> resultList = pageList.stream().map(e -> {
            ActivityGoodsCouponResponse response = new ActivityGoodsCouponResponse();
            response.setId(e.getId());
            response.setName(e.getName());
            response.setType(e.getType());
            response.setTypeName(MerchantCouponTypeEnum.getCodeMessage(e.getType()));
            response.setDenomination(e.getDenomination());
            response.setGetWay(e.getGetWay());
            response.setGetWayName(MerchantCouponGetWayEnum.getCodeMessage(e.getGetWay()));
            response.setUseConditionMoney(e.getUseConditionMoney());
            response.setEffectiveType(e.getEffectiveType());
            response.setEffectiveTypeName(MerchantCouponEffectiveTypeEnum.getCodeMessage(e.getEffectiveType()));
            response.setEffectiveTimeStart(e.getEffectiveTimeStart());
            response.setEffectiveTimeEnd(e.getEffectiveTimeEnd());
            response.setInvalidDay(e.getInvalidDay());
            response.setCreateTime(e.getCreateTime());
            return response;
        }).collect(Collectors.toList());

        return Wrapper.success(new PageData<>(pageList.getTotalElements(), resultList));
    }

    @Override
    public Wrapper<PageData<ActivityPrizeCouponResponse>> selectPrizeCouponList(ActivityMerchantPrizeCouponRequest request, UserLoginCacheDTO loginUser) {
        long currentTimeMillis = System.currentTimeMillis();
        Pageable page = PageRequest.of(request.getCurrent() - 1, request.getPageSize(), Sort.by("releaseTimeStart").descending());
        Page<MerchantCouponDO> pageList = merchantCouponRepository.findAll((Specification<MerchantCouponDO>) (root, query, cb) -> {
            List<Predicate> predicateList = new ArrayList<>();

            // 0元抵扣券
            predicateList.add(cb.equal(root.get("memberId"), loginUser.getMemberId()));
            predicateList.add(cb.equal(root.get("roleId"), loginUser.getMemberRoleId()));
            // 营销活动用券
            predicateList.add(cb.equal(root.get("getWay"), MerchantCouponGetWayEnum.MARKETING.getCode()));
            // 0元抵扣券
            predicateList.add(cb.equal(root.get("type"), MerchantCouponTypeEnum.ZERO_DISCOUNT.getCode()));

            // 当前时间在发券时间内
            predicateList.add(cb.lessThanOrEqualTo(root.get("releaseTimeStart"), currentTimeMillis));
            predicateList.add(cb.greaterThanOrEqualTo(root.get("releaseTimeEnd"), currentTimeMillis));

            if (Objects.nonNull(request.getId())) {
                predicateList.add(cb.equal(root.get("id"), request.getId()));
            }

            if (Objects.nonNull(request.getName())) {
                predicateList.add(cb.equal(root.get("name"), request.getName()));
            }

            Predicate[] p = new Predicate[predicateList.size()];
            return query.where(predicateList.toArray(p)).getRestriction();
        }, page);

        // 适用商品
        List<Long> couponIds = pageList.stream().map(MerchantCouponDO::getId).collect(Collectors.toList());
        List<CouponGoodsDO> goodsDOList = goodsRepository.findAllByBelongTypeAndCouponIdIn(BelongTypeEnum.MERCHANT.getCode(), couponIds);
        Map<Long, List<CouponGoodsDO>> couponGoodsDOMap = goodsDOList.stream().collect(Collectors.groupingBy(CouponGoodsDO::getCouponId));

        List<ActivityPrizeCouponResponse> resultList = pageList.stream().map(e -> {
            ActivityPrizeCouponResponse response = new ActivityPrizeCouponResponse();
            response.setId(e.getId());
            response.setName(e.getName());
            response.setType(e.getType());
            response.setTypeName(MerchantCouponTypeEnum.getCodeMessage(e.getType()));
            response.setDenomination(e.getDenomination());
            response.setGetWay(e.getGetWay());
            response.setGetWayName(MerchantCouponGetWayEnum.getCodeMessage(e.getGetWay()));
            response.setUseConditionMoney(e.getUseConditionMoney());
            response.setEffectiveType(e.getEffectiveType());
            response.setEffectiveTypeName(MerchantCouponEffectiveTypeEnum.getCodeMessage(e.getEffectiveType()));
            response.setEffectiveTimeStart(e.getEffectiveTimeStart());
            response.setEffectiveTimeEnd(e.getEffectiveTimeEnd());
            response.setInvalidDay(e.getInvalidDay());
            response.setCreateTime(e.getCreateTime());

            CouponGoodsDO couponGoodsDO = Optional.ofNullable(couponGoodsDOMap.get(e.getId())).map(list -> list.get(0)).orElse(null);
            if (Objects.nonNull(couponGoodsDO)) {
                SuitableProductVO suitableProductVO = new SuitableProductVO();
                suitableProductVO.setProductId(couponGoodsDO.getProductId());
                suitableProductVO.setSkuId(couponGoodsDO.getSkuId());
                suitableProductVO.setProductName(couponGoodsDO.getProductName());
                suitableProductVO.setType(couponGoodsDO.getType());
                suitableProductVO.setCategory(couponGoodsDO.getCategory());
                suitableProductVO.setBrand(couponGoodsDO.getBrand());
                suitableProductVO.setUnit(couponGoodsDO.getUnit());
                suitableProductVO.setPrice(couponGoodsDO.getPrice());
                suitableProductVO.setProductImgUrl(couponGoodsDO.getProductImgUrl());
                response.setSuitableProduct(suitableProductVO);
            }

            return response;
        }).collect(Collectors.toList());

        return Wrapper.success(new PageData<>(pageList.getTotalElements(), resultList));
    }
}
